/*******************************************************************************
 * Copyright (c) 2010 liw.
 * All rights reserved. 
 * 
 * This file is part of VanBus.
 * 
 *     VanBus is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     VanBus is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with VanBus.  If not, see <http://www.gnu.org/licenses/>.
 * Contributors:
 *     liw - initial API and implementation
 ******************************************************************************/
package org.niclab.vanbus.activity;

import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

import org.niclab.vanbus.R;
import org.niclab.vanbus.application.VanBusApplication;
import org.niclab.vanbus.model.BusRoute;
import org.niclab.vanbus.model.BusStop;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class OverlayMapAct extends MapActivity {

	private static String LOG_TAG = "OverlayMapAct";

	private MapView mapView;
	private MyLocationOverlay myLocationOverlay;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.setTitle("title is unset yet");

		mapView = new MapView(this, this.getString(R.string.google_map_api_key));
		this.setContentView(mapView);

		mapView.setClickable(true);
		mapView.setBuiltInZoomControls(true);

		// overlays
		initOverlays();

	}

	private void initOverlays() {
		List<GeoPoint> points = new ArrayList<GeoPoint>();
		// my location overlay

		List<Overlay> overlayList = mapView.getOverlays();
		myLocationOverlay = new MyLocationOverlay(this, mapView);
		overlayList.add(myLocationOverlay);
		
		if(myLocationOverlay.getMyLocation() !=null)
			points.add(myLocationOverlay.getMyLocation());
		// stops overlay

		BusStop stop = (BusStop) VanBusApplication.getInstance()
				.getAndRemoveTempData(this.getIntent().getStringExtra(getString(R.string.currently_selected_bus_stop)));
		ArrayList<BusStop> stops = new ArrayList<BusStop>();
		stops.add(stop);
		StopOverlay so = new StopOverlay(getResources().getDrawable(R.drawable.busstop), stops);
		
		for(int i=0; i<so.size();i++){
			points.add(so.getItem(i).getPoint());
		}
		overlayList.add(so);
		
		adjustZoomSpan(points);

	}

	private void adjustZoomSpan(List<GeoPoint> points) {
		// Minimum & maximum latitude so we can span it
		// The latitude is clamped between -80 degrees and +80 degrees inclusive
		// thus we ensure that we go beyond that number
		int minLatitude = (int) (+81 * 1E6);

		int maxLatitude = (int) (-81 * 1E6);

		// Minimum & maximum longitude so we can span it
		// The longitude is clamped between -180 degrees and +180 degrees
		// inclusive thus we ensure that we go beyond that number
		int minLongitude = (int) (+181 * 1E6);
		int maxLongitude = (int) (-181 * 1E6);

		

		for(GeoPoint point: points){

            // Sets the minimum and maximum latitude so we can span and zoom
            minLatitude = (minLatitude > point.getLatitudeE6()) ? point.getLatitudeE6() : minLatitude;

            maxLatitude = (maxLatitude < point.getLatitudeE6()) ? point.getLatitudeE6() : maxLatitude;               

            // Sets the minimum and maximum latitude so we can span and zoom

            minLongitude = (minLongitude > point.getLongitudeE6()) ? point.getLongitudeE6() : minLongitude;

            maxLongitude = (maxLongitude < point.getLongitudeE6()) ? point.getLongitudeE6() : maxLongitude;
		}
		
		 // Zoom to span from the list of points
		int latSpan = maxLatitude - minLatitude;
		int lngSpan = maxLongitude - minLongitude;
		
		if(latSpan <=0 && lngSpan <=0)
			mapView.getController().setZoom(15);
		else
			mapView.getController().zoomToSpan(latSpan, lngSpan);

       

        // Animate to the center cluster of points

        mapView.getController().animateTo(new GeoPoint((maxLatitude + minLatitude)/2, (maxLongitude + minLongitude)/2 ));
		
	}

	@Override
	protected boolean isRouteDisplayed() {

		return false;
	}

	@Override
	protected boolean isLocationDisplayed() {
		return true;
	}

	@Override
	protected void onResume() {
		super.onResume();
		myLocationOverlay.enableMyLocation();
		myLocationOverlay.enableCompass();

	}

	@Override
	protected void onPause() {
		super.onPause();
		myLocationOverlay.disableMyLocation();
		myLocationOverlay.disableCompass();

	}

	public class StopOverlay extends ItemizedOverlay<StopItem> {

		List<BusStop> stops;
		MapView mapView;

		public StopOverlay(Drawable defaultMarker, List<BusStop> stops) {

			super(boundCenterBottom(defaultMarker));
			this.stops = stops;
			this.mapView = OverlayMapAct.this.mapView;
			populate();

		}

		@Override
		protected StopItem createItem(int i) {
			try {
				BusStop stop = stops.get(i);

				StopItem oi = new StopItem(stop);

				return oi;
			} catch (IndexOutOfBoundsException ex) {

				return null;
			}
		}

		@Override
		public int size() {

			return stops.size();
		}

		@Override
		protected boolean onTap(int index) {

			StopItem item = getItem(index);

			if ((item.getStopItemState() & StopItem.BUBBLE_TEXT_DISPLAYED) == 0) {
				GeoPoint gp = item.getPoint();
				BusStop stop = item.getBuStop();

				item.createBubbleText(mapView);

			} else {

				item.cancelBubbleText(mapView);

			}
			return true;
		}

	}

	private static class StopItem extends OverlayItem {

		public static int BUBBLE_TEXT_DISPLAYED = 1;

		private int state = 0;

		private BusStop stop;
		private TextView bubbleText;

		public StopItem(BusStop stop) {
			this(stop, stop.getStopId(), stop.getStopName());

		}

		private static GeoPoint getGP(BusStop stop) {
			Double lat = stop.getLatitude() * 1E6;
			Double lng = stop.getLongitude() * 1E6;

			return new GeoPoint(lat.intValue(), lng.intValue());

		}

		public StopItem(BusStop stop, String title, String snippet) {

			super(getGP(stop), title, snippet);
			this.stop = stop;

		}

		public BusStop getBuStop() {
			return stop;
		}

		void addStopItemState(int state) {
			this.state = this.state | state;
		}

		int getStopItemState() {
			return this.state;
		}

		void createBubbleText(MapView view) {
			bubbleText = new TextView(view.getContext());
			bubbleText.setBackgroundColor(view.getResources().getColor(
					android.R.color.background_light));
			bubbleText.setTextColor(view.getResources().getColor(
					android.R.color.black));
			StringBuilder builder = new StringBuilder();
			builder.append(stop.getStopName()).append("\n").append("stop #:")
					.append(stop.getStopId()).append("\n");

			for (Entry<BusRoute, List<String>> x : stop.getBusTimes()
					.entrySet()) {

				builder.append(x.getKey().getRouteId()).append(": ");
				for (String time : x.getValue()) {
					builder.append(time).append(", ");

				}
				builder.setLength(builder.length() - 2);
				builder.append("\n");

			}
			builder.setLength(builder.length() - 1);

			bubbleText.setText(builder.toString());
			MapView.LayoutParams lp = new MapView.LayoutParams(
					MapView.LayoutParams.WRAP_CONTENT,
					MapView.LayoutParams.WRAP_CONTENT, mPoint,
					MapView.LayoutParams.TOP_LEFT);
			view.addView(bubbleText, lp);
			this.state = this.state | BUBBLE_TEXT_DISPLAYED;

		}

		void cancelBubbleText(MapView view) {
			view.removeView(bubbleText);
			this.state = this.state & ~BUBBLE_TEXT_DISPLAYED;

		}
	}
}
